By adding the modifications I now have a completed reaction game. I tend to get scores in the high forties, which is probably quite good for my age. On the right is my program, yours may be better. Don't get discouraged if you haven't written your program exactly the same way as mine. At the end of the day the thing that really counts is whether or not the program does what the user wants.
If your program is fully functional it doesn't matter at all precisely how the code is arranged. If you want to sample my program, and maybe take on some of your friends.
Exercise 8.4
/* EX 8.4 Reaction Timer */
/* David Miles 2006 */
#include <system.h>
#include <lcdlib.h>
/* used to trim the delay loops */
#define SPEED 500
void setup_hardware (void)
{
/* Set PortA to use digital inputs */
ANSELA = 0x00;
/* bits 0-4 of PORTA for input */
TRISA = 0x01 ;
/* Configure the INTCON register */
/* to enable timer interrupts */
INTCON = 0b10100000;
/* Configure the timer to use the prescaler */
OPTION_REG = 0b01000100 ;
}
/* returns the debounced state of */
/* the bottom bit of PORTA */
unsigned char key ( void )
{
unsigned char count = 0 ;
unsigned char oldv, newv ;
oldv = PORTA & 0x01 ;
while ( count < 20 ) {
newv = PORTA & 0x01 ;
if ( oldv == newv ) {
count++ ;
}
else {
count = 0 ;
oldv = newv ;
}
}
return oldv ;
}
/* repeatedly calls key until it is */
/* down */
void keywait ( void )
{
while ( key() == 0 ) ;
}
/* repeatedly calls key until it is */
/* up */
void upwait ( void )
{
while ( key() != 0 ) ;
}
unsigned char timer_active = 0 ;
int time_count = 0 ;
void tmrHandler( void )
{
/* increment the timer if it */
/* has been set to active */
if ( timer_active != 0 ) {
time_count = time_count + 1 ;
}
}
/* This is the interrupt handler */
/* It is called when the PIC */
/* detects an interrupt */
/* It checks the status bits to */
/* find out who caused the */
/* interrupt and then calls that */
/* handler */
unsigned char counter = 0;
void interrupt( void )
{
/* if the timer has overflowed */
/* bit 2 of INTCON is set high */
if( INTCON & 4 )
{
/* clear the bit to turn */
/* off this interrupt */
clear_bit( INTCON, 2 );
counter = counter + 1;
if ( counter > 2 )
{
counter = 0;
/* call the handler */
/* function */
tmrHandler();
}
}
}
void big_delay ( int size )
{
int i, j ;
for ( i=0 ; i < size ; i = i + 1 )
{
for ( j=0 ; j < SPEED ; j=j+1 ) ;
}
}
void display_value ( int value )
{
unsigned char hunds, tens, units ;
/* first get the digits */
units = value % 10 ;
value = value / 10 ;
tens = value % 10 ;
value = value / 10 ;
hunds = value % 10 ;
/* now display them */
lcd_print_ch ( '0' + hunds ) ;
lcd_print_ch ( '0' + tens ) ;
lcd_print_ch ( '0' + units ) ;
}
const unsigned char banner1 [14] =
{
'R','e','a','c','t', 'i', 'o', 'n',
' ','G','a','m','e',0x00
} ;
const unsigned char banner2 [14] =
{
'*','*','*','*','*', '*', '*', '*',
' ','*','*','*','*',0x00
} ;
const unsigned char start1 [] =
{
'P','r','e','s','s',' ',
't','h','e',
0x00
} ;
const unsigned char start2 [] =
{
'b','u','t','t','t','o','n',' ',
't','o',' ',
's','t','a','r','t',0x00
} ;
const unsigned char ready [] =
{
'R','e','a','d','y','.','.',0x00
} ;
const unsigned char foul [] =
{
'*','*','F','O','U','L','*',
'*', 0x00
} ;
const unsigned char score [] =
{
'Y','o','u',' ',
's','c','o','r','e','d',' ',
0x00
} ;
void main ( void )
{
lcd_start () ;
setup_hardware () ;
lcd_cursor ( 0, 0 ) ;
lcd_print ( banner1 ) ;
lcd_cursor ( 0, 1 ) ;
lcd_print ( banner2 ) ;
big_delay ( 1000 ) ;
while (1)
{
lcd_clear () ;
/* turn off LEDS */
PORTA = 0x00 ;
/* display the start message */
lcd_print ( start1 ) ;
lcd_cursor ( 0, 1 ) ;
lcd_print ( start2 ) ;
/* wait for keypress */
keywait () ;
lcd_clear () ;
/* wait for the key up */
upwait () ;
lcd_print ( ready ) ;
big_delay ( 2000 ) ;
/* if the button is down we */
/* have a foul */
if ( key () == 1 ) {
/* -- too early! */
lcd_clear () ;
lcd_print ( foul ) ;
/* wait for the key up */
upwait () ;
/* restart the game */
continue ;
}
/* light the LEDS */
PORTA = 0x1e ;
/* clear the counter */
time_count = 0 ;
/* start it running */
timer_active = 1 ;
/* wait for the button */
keywait () ;
/* stop the timer */
timer_active = 0 ;
lcd_clear () ;
lcd_print ( score ) ;
display_value ( time_count ) ;
keywait () ;
upwait () ;
}
}